﻿Imports System.IO
Imports System.IO.Compression
Friend Class clsPDFDeflateStream
    Inherits Stream
    Private _ds As DeflateStream
    Private _columns, _predicator, _pos, _rowpos As Integer
    Private _prev, _rows As Byte()

    Public Sub New(s As Stream, dict As clsPdfDictionnary)
        Dim decodeParams As clsPdfDictionnary
        If dict.ContainsKey(PDF_DECODEPARMS) Then
            decodeParams = dict.Item(PDF_DECODEPARMS).GetPdfDictionnary
            _columns = CInt(decodeParams.Item(PDF_COLUMNS).GetLong)
            ReDim _prev(_columns - 1)
            ReDim _rows(_columns - 1)
            _rowpos = _rows.Length
            _predicator = CInt(decodeParams.Item(PDF_PREDICATOR).GetLong)
        Else
            _columns = 0
            _predicator = 0
        End If
        s.ReadByte()
        s.ReadByte()
        _ds = New DeflateStream(s, CompressionMode.Decompress, True)
    End Sub
    Public ReadOnly Property Columns As Integer
        Get
            Columns = _columns
        End Get
    End Property
    Public Overrides ReadOnly Property Length As Long
        Get
            Throw New InvalidOperationException
        End Get
    End Property
    Public Overrides ReadOnly Property CanRead As Boolean
        Get
            CanRead = True
        End Get
    End Property
    Public Overrides ReadOnly Property CanWrite As Boolean
        Get
            CanWrite = False
        End Get
    End Property
    Public Overrides ReadOnly Property CanSeek As Boolean
        Get
            CanSeek = False
        End Get
    End Property
    Public Overrides Sub Flush()

    End Sub
    Public Overrides Property Position As Long
        Get
            Position = _pos
        End Get
        Set(value As Long)
            Throw New NotImplementedException
        End Set
    End Property
    Public Overrides Function Read(buffer() As Byte, offset As Integer, count As Integer) As Integer
        Dim ret As Integer = 0
        Dim b, i, len, x, y As Integer
        Dim rlen As Integer


        If _columns = 0 Then
            ret = _ds.Read(buffer, offset, count)
        Else
            While ret < (count - _columns)
                If _rowpos >= _rows.Length Then
                    b = _ds.ReadByte
                    If b < 0 Then
                        Exit While
                    End If
                    If b <> 2 Then
                        Throw New Exception("unknown predictor type")
                    End If
                    Array.Copy(_rows, _prev, _rows.Length)

                    len = _ds.Read(_rows, offset, _rows.Length)
                    If len < _rows.Length - 1 Then
                        Exit While
                    End If

                    For i = 0 To _rows.Length - 1
                        x = _rows(i)
                        y = _prev(i)

                        _rows(i) = CByte((x + y) Mod 256)
                    Next
                    _rowpos = 0
                End If
                rlen = Math.Min(count, _rows.Length - _rowpos)
                Array.Copy(_rows, _rowpos, buffer, ret, rlen)

                ret += rlen
                _rowpos += rlen
            End While
        End If
        _pos += ret
        Read = ret



    End Function
    Public Overrides Function Seek(offset As Long, origin As SeekOrigin) As Long
        Throw New NotImplementedException
    End Function
    Public Overrides Sub Write(buffer() As Byte, offset As Integer, count As Integer)
        Throw New NotImplementedException
    End Sub
    Public Overrides Sub SetLength(value As Long)
        Throw New NotImplementedException
    End Sub
End Class
